Manual for the Editor-Not-Included Assembler, version 1.0

Program and manual (C) Aaron Heiss (heiss@pdx.edu), December 2000


This program is Freeware!  That means a number of things, all of which I will
explain.

You may download, keep, copy and use this program freely, without compensating
its author (me) or distributor in any way whatsoever.

You may upload, distribute or otherwise disseminate this program freely, with my
thanks, provided that (1) you distribute it only in its original, unmodified
form, (2) you include this file with it in the same archive and directory, as
applicable, in its original, unmodified form, and (3) you receive no money at all
for it, except for reasonable compensation for media and shipping (if any).  You
may not sell any mass distribution of this program, with or without any
collection of other software, without my explicit permission.

The nature of this program requires an additional clause.  I make no claim
whatsoever to any software developed with the use of this program; nor do I
accept any responsibility for the functionality of any such software, or any
errors in its object code.  Any software developed with the use of this program
need not be noted as such.  Although this program is Freeware, I make no
requirements about anything developed with it, and you may classify your programs
as Freeware, Shareware, Public Domain, or however else you like.  In short,
whatever code you write with this is yours to do with as you see fit, and I will
take neither credit nor blame for it.


How to Run this Program:

First note that the source code to be assembled must be in standard ProDOS TXT
format; that is, regular ASCII, with all lines terminated by carriage return
characters ($0D) only.  Text will be accepted with or without the high bit set.

This program is a SYS file, which means that it may be launched from any ProDOS
selector or shell, and it will exit to whatever selector or shell is resident in
or specified by the system.  The program itself is complete in the one file, so
that the disk containing it need only be used for initial loading and can be
removed as soon as the program starts.

After launching, the assembler first prompts for the source code pathname.  You
must know this beforehand, and enter it in from the keyboard; there is no catalog
feature.  No extension is assumed for the source file; if one exists, you must
supply it.

When entering a pathname, both the left-arrow key and the DELETE key will
function as a backspace.  ESC will delete the entire entry.  Hitting RETURN with
no input at all will abort the entry.  Pathnames may or may not need to be fully
qualified, depending on whether or not a default pathname is defined, and on
whether or not any currently defined default pathname corresponds to a valid path
on a currently mounted volume.

The assembler next prompts for the object file pathname.  No default exists for
this; you must specify the complete filename.  The provided object code pathname
will be checked to see if it currently exists.  If so, you are asked for
permission to delete that file.  If permission is not given, the assembler will
return to the object file pathname prompt.  Note that this assembler will not
delete locked files.

Once the object pathname has been established, the assembler will prompt for the
filetype of the object program.  Several options are provided as single-key
selections.  They are SYS, BIN, CMD and REL.  There is also an "Other" option,
which enables you to enter in the two-digit hexadecimal filetype code desired. 
Any code may be used; this is not checked by the assembler.

Next, the assembler prompts for the status file pathname.  You may enter one in
or simply press RETURN with no entry present to cancel the creation of a status
file.  If the status file is not cancelled, it will first be checked for by the
assembler, and if a file already exists with the specified pathname, you will be
prompted to delete the file.  If this is not desired, the assembler will prompt
for another status file pathname.  Once again, this assembler will not delete
locked files.

Assembly is an automatic process.  However, if errors are encountered in the
first pass, the assembler will pause between passes and ask permission to
continue.  If permission is denied, the assembler will return to the source file
pathname prompt.

If at any time during its operation the assembler encounters a ProDOS error, it
will report this and abort its operation, returning to the source file pathname
prompt.  Pressing RETURN with a blank line at this prompt will cause the
assembler to quit, returning you to the environment from which the assembler was
launched.


General Syntactic Conventions:

Source code follows the conventional assembler format, with each line divided
into four fields.  An optional label occupies the first field; an instruction or
directive mnemonic must be in the second; an operand, if applicable, is placed in
the third; and any comments desired may be placed in the fourth.

Lines may be any length up to and including 128 bytes.  Any lines longer than
this limit will produce unpredictable results.  Every line must end with a
carriage return character (ASCII $8D), including the last line of the source
file.

At least one space must separate all fields.  However, there is no limit to the
number of spaces that may be used, so long as the entire line is within 128
bytes.  Thus, tabbing may be effected through the use of multiple spaces.

Blank lines are ignored.

All alphabetic characters to be interpreted by the assembler, which is to say all
letters not in comments or explicitly declared as ASCII values, must be
uppercase.  Thus, all mnemonics and all labels can contain no lowercase letters
at all, and the hexadecimal values A through F likewise must be "spelled" in
capitals.

Comments must be preceded by either an asterisk ('*') or a semicolon (';').  If
an entire line is to be used as a comment, one or the other of these characters
must be the first character in that line.

If there is a label in the label field, its first character must be the first
character in the line.  If there is no label in this field, the first character
in the line must be a space character.

Labels must follow the same rules as ProDOS filenames: they must begin with a
letter, contain only letters, numbers and the period ('.'), and may be one to
fifteen characters in length.

No spaces are allowed within an operand, the only exceptions being ASCII codes
preceded by an apostrophe (') and spaces within strings.


Syntactic Conventions of Operands:

All instructions with no operand and no register or flag explicit in their
mnemonics are assumed to be accumulator mode.  Thus, LSR by itself will be
accumulator mode; LSR A will be assumed to refer to a label called A, and will
produce an error if no such label exists.  Note that this includes the 65c02-only
instructions INC and DEC.  However, the mnemonics INA and DEA are also supported.

All operands indicate zero page mode (if available) if their high byte is zero. 
Absolute mode may be specified by prefixing the operand with a carat (^), so if
LABEL is equated to $0042, instructions such as STA LABEL will be in zero page
mode, while STA ^LABEL will be in absolute mode.

The low-order byte of an operand can be specified by the less-than sign (<), and
the high-order byte can be specified by the greater-than sign (>).  These
qualifiers will specify zero page mode if applicable.  Note, however, that an
expression such as LDA ^>$1234 will produce an error.

Immediate addressing mode is specified by prefixing the operand with a number
sign (#).  This must be the first character in the operand field; if other
qualifiers are used, they must follow this sign.

All hexadecimal values must be prefixed by a dollar sign ($).  All binary values
must be similarly prefixed by a percent sign (%).  ASCII codes may be included as
values (with the high bit set) if preceded by an apostrophe (').  Thus, LDA #'A
is equivalent to LDA #$C1.  These signs must be after any other prefixes and
adjacent to the value itself.  Decimal values neither require nor allow any
special declaration.  Labels also neither require nor allow any special
declaration, but they must follow the naming conventions given above.

Values may be computed.  Addition and subtraction are allowed using the regular
signs (+ and -), and may be compounded.  Compound computations are processed in a
left-to-right order, and parentheses are not allowed.  The minus sign may not be
used to specify a negative value by itself; if one is desired, an expression such
as 0-VALUE is necessary.

All values are stored internally as two-byte numbers.  Single-byte values are
thus stored with their high-order bytes equal to zero, and can be referred to as
double-byte values if desired (using the carat as outlined above).  Values
requiring more than two bytes will be truncated.  Thus, $12345 will be cut to
$2345, and 65537 will be equal to 1.


Directives:

Four directives are supported by this assembler.

DEF defines its operand as data to be inserted into the object code.  No label is
required for this directive to function.  Data can be of any legal type, and may
consist of single-byte values, double-byte values (always stored low-order byte
first), or strings.  Multiple units of data may be included with one DEF,
provided that all are separated by commas (,) only with no spaces.  Each unit of
data must be individually specified; that is, each hexadecimal number must have
its own dollar sign ($) prefix, each binary number its own percent sign (%)
prefix, and so on.  Multiple types of data may be mixed together as desired.  In
addition, strings may be specified (always assembled with the high bit of each
character set) merely by enclosing the string in double quotes (").  A double
quote character may be included in the string by repeating it ("").

EQU specifies that a label be equated to a value for internal use by the
assembler.  It is important to note that EQU does not assemble to anything at all
by itself.  If there is no label specified in the label field, this directive
will essentially be ignored.

ORG specifies the origin of the object code.  There must be at least one ORG in
any program, and it may not be of the value $0000, as this is used internally to
indicate "no origin."  Multiple ORGs are allowed, however, to permit the
development of self-relocating code.  Note that the first ORG is used by the
assembler to specify the AUXTYP field of the object code.  Note also that files
of type SYS require that the first ORG be $2000.

SPC is used to insert the number of bytes specified in the operand into the
source file.  These bytes are initialised to zero, so that SPC 12 will insert
twelve zeroes into the object code.  Also, the special case of SPC 0 is
supported, so that a label may be used to indicate a particular position in the
program with no addition being made to the object code.  This is of particular
value if a label is required for the end of the file.


Understanding and Coping with Error Messages

I have tried to keep the error messages as informative as possible while keeping
them short enough to display on one 40-column line.  Obviously, this means that I
have had to make some compromises, and in some cases their meaning may not be
clear.  Hopefully, this will help.

"Bad addressing mode"  The addressing mode might be valid for some instructions,
but not the instruction in this line's opcode field.  This error often results
from a lapse in memory of what addressing modes the 65c02 will and will not allow
with which instructions.

"Branch out of range"  This very common error results from the source and
destination points of a branch instruction being more than 127 bytes apart if the
branch goes forward, or 128 if it goes backward.  Fixing this situation means
that either code will need to be removed between the two points, or the
destination will have to be moved, perhaps to a JMP instruction.

"Disk full."  Every disk has a finite amount of storage space, and the disk you
have specified has reached its.  Use another disk, or quit the assembler and
erase or abbreviate files on the present disk to make more room.

"Disk write protected."  This is pretty obvious.  Either you don't want to write
to the disk being accessed, or you will have to take it out of the drive and
remove its write-protect tab.

"Duplicate label"  This assembler allows only one instance of each label in all
the label fields of the source code.  The indicated line is the second (or third,
or fourth...) line with the same label in the label field.

"Duplicate filename."  At least two of the pathnames that you gave the assembler
are identical, and that the assembler is trying to access one of them for the
wrong purpose.  For instance, you could have requested a status file with the
same name as your object file.

"File access denied."  This means that the assembler has tried to write to or
delete a write- or delete-protected file.  Unfortunately, this assembler cannot
unlock such locked files, and so you will either have to specify another
pathname, use another disk, or leave the assembler and unlock the files in
question yourself.

"File already open."  The assembler did not abort a prior operation properly.  It
will close the file in question after it gives this message, though, and if you
try again you should not have this problem.  If this condition persists, hit
CONTROL-RESET; this will always close all open files.

"I/O error."  This is something of a catch-all, as it could indicate anything
from an unformatted disk to a faulty disk drive or controller.  In any event, the
volume accessed is not available to ProDOS.  Hopefully, you have made a backup!

"Illegal label"  All labels must start with an uppercase letter, contain only
uppercase letters, numbers and the dot (.), and be at most fifteen characters
long.  These are the same rules that must be followed by ProDOS filenames, which
should help you remember them.

"Illegal operand"  Operands must follow rigid syntax requirements, which are
outlined above.  Violation of those requirements (a hexadecimal number without a
leading dollar sign, for instance) will result in this error, as will characters
not allowed in the operand field (lowercase letters not in a string are a good
example) and poorly-defined addressing modes, such as indirect with only one
parenthesis or indexed with nothing following the comma.  Essentially, this is a
basic syntax error.

"Input buffer overflow"  This means that the indicated line is over 128 bytes in
length.  Actually, I would not recommend lines over 80 characters in length as
they are difficult to read on a standard Apple II display, but you might disagree
with me, so I allowed more.

"Label not found"  A label was referenced that has not been defined elsewhere in
the program.  Besides the obvious possibility that you forgot to declare the
label, it is also possible that you changed a label's name everywhere but in the
indicated line, or that you inadvertantly deleted a line with the label's
declaration.

"No instruction found"  Every line that does not start with an asterisk or a
semicolon must have something in the opcode field.  Thus, a label by itself is
not a complete line, and will return this error message.

"No operand found"  Instructions with only two- and/or three-byte addressing
modes require an operand.  This error condition may result in unequal length
passes.

"No operand needed"  An operand was found for an instruction with only a
single-byte addressing mode, such as TYA or RTS.  This will result from a comment
with no semicolon or asterisk delineator.

"No ORG found."  All programs must have at least one ORG directive, preferably
before any code-producing opcodes (all 65c02 instructions and the DEF and SPC
directives).  There is no corresponding error for multiple ORGs, as this is
necessary for self-relocating code.

"Operation aborted."  An error occurred that was so severe that the assembler
could not continue assembling.  This always happens after a ProDOS error.  It
means that the system has been returned to the state it was in just after the
assembler was loaded.

"Passes assembled to unequal length."  Some instructions that were assembled to
three bytes in the first pass were assembled to two in the second, or vice versa.
 I will admit that this is a difficult error to deal with.  Some cases are
obvious.  The most likely is that you have declared a label with EQU to be a
zero-page location after it was first referenced as data.  The assembler assumes
that all such forward references are to two-byte values, so it is important that
you place all zero-page EQU's before their first reference.  Another case is that
expressions like STY ^ADDR,X are only allowed two bytes by the 65c02, although
the carat prefix indicates to the assembler to produce a three-byte instruction.
My tactic when correcting this error is to locate the disparity.  To do this, you
can assemble the code to a BIN file and load it under BASIC, switch to the
Monitor, and use the disassembler in ROM to locate JSR's and references to easily
identifiable data.  Check the entry points of the JSR's, and try to track down
the location of the disparity.  Sometimes it helps to add SPC's or DEF's with
recognisable data, like all $FF's or sequences like $00,$11,$22,..., and to try
and locate whether or not these appear in the right places.  Once you have
located the disparity, you can get a better idea of what might be wrong in the
source code.

"Pathname not found."  This could mean one of three things: the disk you
specified is not currently mounted, any subdirectories that you specified may not
exist, or the filename itself is not present.  This could simply be a result of a
misspelling, or you may not be remembering the complete pathname correctly.

"Required memory is not free."  The assembler cannot run because ProDOS has not
been told that the memory that it needs to run has been freed.

"Source file is not of type TXT."  The specified source code is not stored in the
proper format.  This could mean that the source code is stored in a non-text
format, or it could mean that the word processor or text editor used to create or
edit the file uses a proprietary format, that is, something other than plain
ASCII (AppleWorks does this).  Most word processors that do this have an option
to save to a plain text file.  If you get this message under these circumstances,
you must quit the assembler (just hit RETURN at the source code prompt without
any file entry), launch your word processor, load your file, and save it as a
plain text file in order for this assembler to be able to use it.

"Symbol table overflow"  There is no fixed limit to the number of symbols that
this assembler will allow, but there is a limit to the size of the symbol table. 
Longer labels will take up more room than shorter ones, so this error may simply
indicate that you use shorter labels.  Also, programs or data that remain
resident in high RAM will reduce the amount of memory available for the symbol
table.  Quitting the assembler and removing these programs or data will help.

"SYS file requires ORG at $2000."  ProDOS requires that all files of type SYS
have their loading point at $2000.  There are other things that are a good idea
to have a SYS file do, and if you do not know them, perhaps you should not be
writing a SYS file in the first place!

"This program uses 65c02 instructions."  This is not really an error message, but
it does have implications for compatibility.  It means that your program uses
65c02-only instructions, like STZ or BRA, or original 6502 instructions with
65c02-only addressing modes, like LDA (ZP) or DEC.  The program may work fine on
an Apple //c, an expanded //e or a IIgs, but it will not behave itself on an
original //e or anything earlier.

"Unknown instruction"  The assembler will recognise only valid 65c02 instructions
and its own four directives in the opcode field.  Using other assemblers'
directives will return this message (for instance, using DFB, DW or ASC instead
of DEF), as will any misspellings.

"Volume directory full."  ProDOS allows the main directory on the disk to contain
at most only 51 files, and you have asked it to provide a 52nd.  Subdirectories
have no such limit, however, and if you specify a path that uses one, you will
avoid this problem.  You could also use another disk, of course.


Final Note:

This project has taken a great deal of my time and energy, and I would like
nothing more than to see that others appreciate that.  If you find this program
at all useful, I would greatly appreciate hearing from you.  If you find it
lacking, let me know, and I might add your suggestions to the next version!  In
fact, the development of a next version may very well depend on feedback from
interested users, as I do not at this point know whether or not I will want or
need anything more sophisticated than this program is right now.  Be aware,
though, that I may not be able to include any such suggestions for a number of
reasons, as you should expect from your own experience with assembly language
programming. In any event, I hope that you will find this program to be of use,
and that you will tell me about your experiences with it.  Happy assembling!
